/*
 * Hyuga: A Density-Grid Stream Clustering Platform.
 * Copyright (C) 2014 PUC-Rio/Laboratory for Advanced Collaboration
 *
 * Hyuga is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Hyuga is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Hyuga.  If not, see <http://www.gnu.org/licenses/>.
 */
package br.pucrio.inf.lac.konoha.hyuga.events.cell;

import java.util.UUID;

import br.pucrio.inf.lac.konoha.hyuga.events.LocationUpdateEvent;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

/**
 * Represent a context partition (cell) clustering event. The event is emitted when a context partition (cell) detects
 * a cluster, i.e., when the number of mobile nodes mapped to the context partition is over 1.21 minPts.
 * 
 * @author Marcos Roriz <mroriz@inf.puc-rio.br>
 */
@JsonIgnoreProperties(ignoreUnknown = true)
public class CellClusterEvent2 extends CellContentEvent {

    // Neighbor cells
    private CellContentEvent[] neighborCells;

    // Manual nodes counter (for DBSCAN offline check)
//    private int numNodes;
    
    public CellClusterEvent2() {
        super();
    }

    // Basic Constructor
    public CellClusterEvent2(int x, int y, LocationUpdateEvent[] nodes) {
//        super(x, y, nodes);
    }
    
    /**
     * Verify if a given mobile node is inside this cluster, using its UUID {@link UUID}.
     * 
     * @param uuid
     * @return true if mobile node is in the cluster nodes, false otherwise.
     */
    public boolean containsUUID(UUID uuid) {
        boolean contained = false;
//        for (LocationUpdateEvent node : nodes) {
//            if (node.getUuid().equals(uuid)) {
//                contained = true;
//                break;
//            }
//        }
        return contained;
    }
    
    /**
     * Verify if a given mobile node is inside this cluster, using its {@link LocationUpdateEvent}.
     * 
     * @param location update
     * @return true if mobile node is in the cluster nodes, false otherwise.
     */
    public boolean contains(LocationUpdateEvent node) {
        // TODO: do a full check, case x and y are equal but it's an old event.
        return (x == node.getX()) && (y == node.getY());
    }
    
    /**
     * Retrieve the number of mobile nodes in the cell, using their UUID (from {@link LocationUpdateEvent}) in the cell.
     * 
     * @return the number of mobile nodes in the cell.
     */
    public double numNodes() {
        return 0;
    }
    
    //////////////////////////////////////////////////////////////////////////
    // DBSCAN helpers methods
    //////////////////////////////////////////////////////////////////////////
    
//    /**
//     * Add a mobile node (using its location update) to the cluster.
//     * @param node
//     */
//    public void addNode(LocationUpdateEvent node) {
//        if (size() >= nodes.length) {
//            LocationUpdateEvent[] newnodes = new LocationUpdateEvent[nodes.length * 5];
//            System.arraycopy(nodes, 0, newnodes, 0, nodes.length);
//            nodes = newnodes;
//        }
////        nodes[(int) numNodes++] = node;
//    }

    // FIXME: Review equal and hashcode method.
//    @Override
//    public boolean equals(Object obj) {
//        try {
//            CellClusterEvent partition = (CellClusterEvent) obj;
//            if ((this.x == partition.getX()) && (this.y == partition.getY())) {
//                return true;
//            } else {
//                return false;
//            }
//        } catch (ClassCastException ex) {
//            ex.printStackTrace();
//            return false;
//        }
//    }
//
//    @Override
//    public int hashCode() {
//        int hashX = 0;
//        int hashY = 0;
//
//        return hashX + hashY + (hashX * hashY) + (hashX * hashX) + (hashY * hashY);
//    }

    //////////////////////////////////////////////////////////////////////////
    // Gets and Sets
    //////////////////////////////////////////////////////////////////////////

    public CellContentEvent[] getNeighborCells() {
        return neighborCells;
    }
    
    public void setNeighborCells(CellContentEvent[] neighborCells) {
        this.neighborCells = neighborCells;
    }
    
    public String toString() {
        StringBuilder sb = new StringBuilder();
//        sb.append("CLUSTER (").append(x).append(", ").append(y).append(") - ").append(numNodes).append(" - ");
        
        if (neighborCells != null) {
            sb.append("NEIGHBORS [");
            String delim = "";
            for (CellContentEvent neighbor : neighborCells) {
                sb.append(delim).append("(").append(neighbor.getX()).append(", ").append(neighbor.getY()).append(") ");
                delim = ",";
            }
            sb.append("]");
        }
        
        return sb.toString();
    };
}
